﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ip_problem1
{
    abstract public class Masina
    {
        string _Culoare;
        string _Transmisie;
        public string Culoare
        {
            get
            {
                return _Culoare;
            }
            set
            {
                _Culoare = value;
            }
        }
        public string Transmisie
        {
            get
            {
                return _Transmisie;
            }
            set
            {
                _Transmisie = value;
            }
        }
        public virtual void Print()
        {
            Console.WriteLine("culoare : " + _Culoare);
            Console.WriteLine("transmisie : " + _Transmisie);
        }
    }

    public interface ModelFactory
    {
        Masina CreateMasina();
    }

    class Sedan : Masina
    {
        string _Dotari;
        string _Motorizare;
        string _Dimensiuni;
        public string Dotari
        {
            get
            {
                return _Dotari;
            }
            set
            {
                _Dotari = value;
            }
        }
        public string Motorizare
        {
            get
            {
                return _Motorizare;
            }
            set
            {
                _Motorizare = value;
            }
        }
        public string Dimensiuni
        {
            get
            {
                return _Dimensiuni;
            }
            set
            {
                _Dimensiuni = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Model Sedan");
            Console.WriteLine("dotari : " + _Dotari);
            Console.WriteLine("motorizare : " + _Motorizare);
            Console.WriteLine("dimensiuni : " + _Dimensiuni);
            base.Print();
        }
    }

    class Coupe : Masina
    {
        string _Dotari;
        string _Motorizare;
        string _Dimensiuni;
        public string Dotari
        {
            get
            {
                return _Dotari;
            }
            set
            {
                _Dotari = value;
            }
        }
        public string Motorizare
        {
            get
            {
                return _Motorizare;
            }
            set
            {
                _Motorizare = value;
            }
        }
        public string Dimensiuni
        {
            get
            {
                return _Dimensiuni;
            }
            set
            {
                _Dimensiuni = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Model Coupe");
            Console.WriteLine("dotari : " + _Dotari);
            Console.WriteLine("motorizare : " + _Motorizare);
            Console.WriteLine("dimensiuni : " + _Dimensiuni);
            base.Print();
        }
    }

    class Mini : Masina
    {
        string _Dotari;
        string _Motorizare;
        string _Dimensiuni;
        public string Dotari
        {
            get
            {
                return _Dotari;
            }
            set
            {
                _Dotari = value;
            }
        }
        public string Motorizare
        {
            get
            {
                return _Motorizare;
            }
            set
            {
                _Motorizare = value;
            }
        }
        public string Dimensiuni
        {
            get
            {
                return _Dimensiuni;
            }
            set
            {
                _Dimensiuni = value;
            }
        }

        public override void Print()
        {
            Console.WriteLine("Model Mini");
            Console.WriteLine("dotari : " + _Dotari);
            Console.WriteLine("motorizare : " + _Motorizare);
            Console.WriteLine("dimensiuni : " + _Dimensiuni);
            base.Print();
        }
    }

    class SedanFactory : ModelFactory
    {
        Masina ModelFactory.CreateMasina()
        {
            Sedan s = new Sedan();
            Console.WriteLine("dotari : ");
            string a = Console.ReadLine();
            s.Dotari = a;
            Console.WriteLine("motorizare : ");
            a = Console.ReadLine();
            s.Motorizare = a;
            Console.WriteLine("dimensiuni : ");
            a = Console.ReadLine();
            s.Dimensiuni = a;
            return s;
        }
    }

    class CoupeFactory : ModelFactory
    {
        Masina ModelFactory.CreateMasina()
        {
            Coupe s = new Coupe();
            Console.WriteLine("dotari : ");
            string a = Console.ReadLine();
            s.Dotari = a;
            Console.WriteLine("motorizare : ");
            a = Console.ReadLine();
            s.Motorizare = a;
            Console.WriteLine("dimensiuni : ");
            a = Console.ReadLine();
            s.Dimensiuni = a;
            return new Coupe();
        }
    }

    class MiniFactory : ModelFactory
    {
        Masina ModelFactory.CreateMasina()
        {
            Mini s = new Mini();
            Console.WriteLine("dotari : ");
            string a = Console.ReadLine();
            s.Dotari = a;
            Console.WriteLine("motorizare : ");
            a = Console.ReadLine();
            s.Motorizare = a;
            Console.WriteLine("dimensiuni : ");
            a = Console.ReadLine();
            s.Dimensiuni = a;
            return new Mini();
        }
    }

    class Client
    {

        string _Nume;
        int varsta;
        List<Masina> masini;

        public Client() { masini = new List<Masina>(); }
        public string Nume
        {
            get
            {
                return _Nume;
            }
            set
            {
                _Nume = value;
            }
        }
        public Masina addMasina(ModelFactory model)
        {
            Masina masina = model.CreateMasina();
            masini.Add(masina);
            return masina;
        }
        public void removeMasina(string tip)
        {
            foreach (Masina m in masini)
            {
                if (m.GetType().ToString().ToLower().EndsWith(tip))
                {
                    masini.Remove(m);
                    break;
                }
            }
        }
        public void Print()
        {
            Console.WriteLine("Nume : " + _Nume);
            foreach (Masina m in masini)
            {
                m.Print();
            }
        }
    }

    public class ClientRunner
    {
        static public ModelFactory SpecificModel(string model)
        {
            if (model.Equals("sedan"))
                return new SedanFactory();
            if (model.Equals("coupe"))
                return new CoupeFactory();
            else return new MiniFactory();
        }
    }

    class ClientPool
    {
        static readonly List<Client> clientPool = new List<Client>();
        static readonly Lazy<ClientPool> _cp = new Lazy<ClientPool>(() => new ClientPool());
        public static ClientPool Instance { get { return _cp.Value; } }
        public Client GetClient(string nume)
        {
            Client client;
            // verificare in pool, daca exita returnam, altfel creem unul nou
            client = RetrieveFromPool(nume);
            if (client == null)
            {
                client = GetNewEmployee(nume);
            }
            return client;
        }
        private Client GetNewEmployee(string nume)
        {
            Client client = new Client();
            client.Nume = nume;
            clientPool.Add(client);
            return client;
        }
        private Client RetrieveFromPool(string nume)
        {
            foreach (Client client in clientPool)
            {
                if (client.Nume.Equals(nume))
                {
                    return client;
                }

            }
            return null;
        }
        public void Print()
        {
            foreach (Client client in clientPool)
            {
                client.Print();
                Console.WriteLine();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ClientPool pool = new ClientPool();
            string nume;
            Client client;
            while (true)
            {
                Console.WriteLine("1. Print Clienti \n2.New Client \n3.Add Masina\n4.Sterge Masina\nq.Exit");
                char k = Console.ReadLine()[0];
                Console.Clear();
                switch (k)
                {
                    case '1': pool.Print(); break;
                    case '2': Console.Write("Dati numele clientului: ");
                         nume = Console.ReadLine();
                         client = pool.GetClient(nume); break;
                    case '3':
                        Console.Write("Dati numele clientului: ");
                         nume = Console.ReadLine();
                         client = pool.GetClient(nume);
                        Console.Write("Dati tipul masinii(sedan,coupe,mini): ");
                        string tip = Console.ReadLine();
                        Masina m;
                        if (tip.Equals("sedan") || tip.Equals("coupe") || tip.Equals("mini"))
                        {
                            m = client.addMasina(ClientRunner.SpecificModel(tip));
                            Console.WriteLine("culoare : ");
                            string c = Console.ReadLine();
                            m.Culoare = c;
                            Console.WriteLine("transmisie : ");
                            string t = Console.ReadLine();
                            m.Transmisie = t;
                        }
                        break;
                    case '4': Console.Write("Dati numele clientului: ");
                        nume = Console.ReadLine();
                        client = pool.GetClient(nume);
                        Console.Write("Dati tipul masinii: ");
                        string tt = Console.ReadLine();
                        client.removeMasina(tt);
                        break;
                    case 'q': return;
                }
                
            }
        }
    }
}
